'''
由于闭包这个概念比较难以理解，尤其是初学者来说，相对难以掌握，所以我们通过示例去理解学习闭包。

给大家提个需求，然后用函数去实现：完成一个计算不断增加的系列值的平均值的需求。

例如：整个历史中的某个商品的平均收盘价。什么叫平局收盘价呢？就是从这个商品一出现开始，每天记录当天价格，然后计算他的平均值：平均值要考虑直至目前为止所有的价格。

比如大众推出了一款新车：小白轿车。

第一天价格为：100000元，平均收盘价：100000元

第二天价格为：110000元，平均收盘价：（100000 + 110000）/2 元

第三天价格为：120000元，平均收盘价：（100000 + 110000 + 120000）/3 元

'''
#方案一
l1=[]#全局变量，数据不安全
def make_average(new_value):
    l1.append(new_value)
    total=sum(l1)
    average=total/len(l1)
    return average
print(make_average(100000))
print(make_average(110000))
print(make_average(120000))
print('*'*50)

#方案二
def make_average(new_value):
    l1=[]#每次执行都会重新赋值为[]
    l1.append(new_value)
    total=sum(l1)
    average=total/len(l1)
    return average
print(make_average(100000))
print(make_average(110000))
print(make_average(120000))
print('*'*50)
#方案三，闭包
def make_average():
    l1=[]#闭包里面，l1为自由变量,与内嵌函数有个绑定关系，不会消失,其他函数里的局部变量会
    def average(new_value):
        l1.append(new_value)
        total=sum(l1)
        return total / len(l1)
    return average
avg=make_average()#调用函数，函数就会消失，
print(avg(100000))
print(avg(110000))
print(avg(120000))
print(globals())
#内层函数对外层函数非全局变量的引用(使用),就会形成闭包
#被引用的非全局变量也称自由变量，这个自由变量会与内层函数产生一个绑定关系
#自由变量不会在内存中消失
#闭包作用：保护数据的安全
def make_average():
    l1=[]#闭包里面，l1为自由变量,与内嵌函数有个绑定关系，不会消失,其他函数里的局部会变量
    print(l1)
    def average(new_value):
        l1.append(new_value)
        print(l1)
        total=sum(l1)
        return total / len(l1)
    return average
avg=make_average()#调用函数，函数就会消失，
print(avg(100000))
print(avg(110000))
print(avg(120000))
#判断是不是闭包函数
# 例一：
def wrapper():
    a = 1
    def inner():
        print(a)
    return inner
ret = wrapper()
#YES
# 例二：
a = 2
def wrapper():
    def inner():
        print(a)
    return inner
ret = wrapper()
#NO
# 例三：

def wrapper(a,b):
    def inner():
        print(a)
        print(b)
    return inner
a = 2
b = 3
ret = wrapper(a,b)
#YES

def make_averager():

    series = []
    def averager(new_value):
        series.append(new_value)
        total = sum(series)
        return total/len(series)

    return averager
avg = make_averager()
# 函数名.__code__.co_freevars 查看函数的自由变量
print(avg.__code__.co_freevars)  # ('series',)
#当然还有一些参数，仅供了解

# 函数名.__code__.co_freevars 查看函数的自由变量
print(avg.__code__.co_freevars)  # ('series',)
# 函数名.__code__.co_varnames 查看函数的局部变量
print(avg.__code__.co_varnames)  # ('new_value', 'total')
# 函数名.__closure__ 获取具体的自由变量对象，也就是cell对象。
# (<cell at 0x0000020070CB7618: int object at 0x000000005CA08090>,)
# cell_contents 自由变量具体的值
print(avg.__closure__[0].cell_contents)  # []


















